<template>
  <div class="panel" :style="`width:${panelwidth};height:${panelheight}`">
    <!-- 内容区 -->
    <a-row type="flex" class="panel-body" :style="`height:${bodyheight}`">
      <!--索引列 -->
      <a-col v-if="showIndex" flex="44px" class="panel-body-index">
        <ul>
          <li
            v-for="(product, index) in data"
            :key="product.key"
            :class="{ 'letter-li': index === letterIndex }"
            @click="onLetterLiClick(product.key, index)"
          >
            {{ product.key }}
          </li>
        </ul>
      </a-col>
      <!--固定第一列 -->
      <a-col flex="156px" class="panel-body-first">
        <div v-for="item in data" :key="item.key" class="first-col">
          <div v-if="showIndex" :class="`first-col-${item.key}`">
            {{ item.name }}
          </div>
          <ul>
            <li
              v-for="product in item.products"
              :key="product.key"
              :class="{
                'active-li':
                  selectedItems[0] && selectedItems[0].key == product.key,
              }"
            >
              <span>
                <input type="checkbox" :checked="isAllSelected(product._fullKey)" @click="e=>selectAll(e.target.checked,product._fullKey)" />
                <span @click="onLevalClick(product, product._fullKey, 0)">{{
                  product.name
                }}</span>
              </span>
              <span>{{ getSelectedCount(product._fullKey) }}</span>
            </li>
          </ul>
        </div>
      </a-col>
      <!-- 动态加载数据列 -->
      <a-col
        v-for="levalItem in leval"
        :key="levalItem"
        flex="auto"
        class="panel-body-auto"
      >
        <div v-if="selectedItems[levalItem - 1]">
          <div class="auto-col">
            <ul>
              <li
                v-for="product in getProductChildrenByLeval(levalItem - 1)"
                :key="product.key"
                :class="{
                  'active-li':
                    selectedItems[levalItem] &&
                    selectedItems[levalItem].key == product.key,
                }"
              >
                <span>
                  <input type="checkbox" :checked="isAllSelected(product._fullKey)" @click="e=>selectAll(e.target.checked,product._fullKey)"/>
                  <span
                    @click="onLevalClick(product, product._fullKey, levalItem)"
                    >{{ product.name }}</span
                  >
                </span>
                <span>{{ getSelectedCount(product._fullKey) }}</span>
              </li>
            </ul>
          </div>
        </div>
        <div
          v-else
          style="
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  height: 100%;
                "
        >
          <span>请点击品牌来选择车型</span>
        </div>
      </a-col>
      <!--固定 最后一列 -->
      <a-col flex="156px" class="panel-body-last" v-if="selectedItems[0]">
        <div v-if="getProductChildrenByLeval(leval).length>0">
          <div class="last-col">
            <ul>
              <li
                v-for="product in getProductChildrenByLeval(leval)"
                :key="product.key"
              >
                <span>
                  <input
                    type="checkbox"
                    :checked="product._selected"
                    @click="selectItem(product._fullKey)"
                  />
                  {{ product.name }}
                </span>
              </li>
            </ul>
          </div>
        </div>
        <div
        v-else
          style="
                  display: flex;
                  align-items: center;
                  justify-content: center;
                  height: 100%;
                "
        >
          <span>请点击车型来选择型号</span>
        </div>
      </a-col>
    </a-row>
    <div class="panel-footer">
      <div>
        <span @click="showSelected">查看已选</span><span>({{ allSelectedProducts.length }})</span>
      </div>
      <div>
        <a-button size="large" @click="checkAll(false)">重置</a-button
        ><a-button size="large" @click="checkAll(true)">全选</a-button
        ><a-button size="large" type="primary" @click="onConfirm">确定</a-button>
      </div>
    </div>
    <a-modal
      v-model="isShowSelected"
      width="700px"
      :footer="null"
      :mask="false"
      title="已选"
    >
      <div v-if="allSelectedProducts && allSelectedProducts.length > 0">
        <a-table :columns="tableColums" :data-source="allSelectedProducts">
          <span slot="action" slot-scope="text, record">
            <a-button
              size="small"
              @click="
                deleteFromAllSeletedProducts(record.key)
              "
              >删除</a-button
            >
          </span>
        </a-table>
      </div>
    </a-modal>
  </div>
</template>
<script>
export default {
  props: {
    panelwidth: {
      type: String,
      default: "500px",
    },
    panelheight: {
      type: String,
      default: "444px",
    },
    bodyheight: {
      type: String,
      default: "375px",
    },
    // 是否显示索引
    showIndex: {
      type: Boolean,
      default: true,
    },
    levalCount: {
      type: Number,
      validator(value) {
        return value >= 2;
      },
      default() {
        return 3;
      },
    },
    selectedTableColumnTitles: {
      type: Array,
      default() {
        return ["第1列", "第2列", "第3列"];
      },
    },
    dataLoader: {
      type: Function,
      default(product, key, leval, callback) {
        let products = [];
        //模拟查询数据
        for (let i = 0; i < 10; i++) {
          products.push({
            key: key + "-" + i,
            name: key + "-" + i,
          });
        }
        callback(products);
      },
    },
  },
  data() {
    return {
      isShowSelected: false, //查看已选
      letterIndex: -1,
      data: [
        {
          key: "B",
          name: "B",
          products: [
            {
              key: 1965,
              name: "奔腾",
              products: [
                {
                  key: 65111,
                  name: "奔腾-1",
                  products: [
                    {
                      key: 651111,
                      name: "奔腾-1-1",
                      products:[]
                    },
                    {
                      key: 651112,
                      name: "奔腾-1-2",
                      products:[]
                    }
                  ]
                },
                {
                  key: 65112,
                  name: "奔腾-2",
                  products: [
                    {
                      key: 652222,
                      name: "奔腾-2-1",
                      products:[]
                    },
                    {
                      key: 652223,
                      name: "奔腾-2-2",
                      products:[]
                    },
                  ]
                }
              ],
            },
            {
              key: 1966,
              name: "奔驰",
              products: [
                {
                  key: 66111,
                  name: "奔驰-1",
                  products: [
                    {
                      key: 661111,
                      name: "奔驰-1-1",
                      products:[]
                    },
                    {
                      key: 661112,
                      name: "奔驰-1-2",
                      products:[]
                    }
                  ]
                },
                {
                  key: 66112,
                  name: "奔驰-2",
                  products: [
                    {
                      key: 662222,
                      name: "奔驰-2-1",
                      products:[]
                    },
                    {
                      key: 662223,
                      name: "奔驰-2-2",
                      products:[]
                    },
                  ]
                }
              ],
            },
          ]
        },
        {
          key: "D",
          name: "D",
          products: [
            {
              key: 1967,
              name: "东风",
              products: [
                {
                  key: 67111,
                  name: "东风-1",
                  products: [
                    {
                      key: 671111,
                      name: "东风-1-1",
                      products:[]
                    },
                    {
                      key: 671112,
                      name: "东风-1-2",
                      products:[]
                    }
                  ]
                },
                {
                  key: 67112,
                  name: "东风-2",
                  products: [
                    {
                      key: 672222,
                      name: "东风-2-1",
                      products:[]
                    },
                    {
                      key: 672223,
                      name: "东风-2-2",
                      products:[]
                    },
                  ]
                }
              ],
            },
            {
              key: 1968,
              name: "DS",
              products: [
                {
                  key: 68111,
                  name: "DS-1",
                  products: [
                    {
                      key: 681111,
                      name: "DS-1-1",
                      products:[]
                    },
                    {
                      key: 681112,
                      name: "DS-1-2",
                      products:[]
                    }
                  ]
                },
                {
                  key: 68112,
                  name: "DS-2",
                  products: [
                    {
                      key: 682222,
                      name: "DS-2-1",
                      products:[]
                    },
                    {
                      key: 682223,
                      name: "DS-2-2",
                      products:[]
                    },
                  ]
                }
              ],
            },
          ]
        },
      ],
      productLists: {}, // 保存每个leval的选中的记录
      selectedItems: {}, //保存当前leval选中的记录
      dynamicProductList: [], // 动态产品列表：点击载入的列表
      allSelectedProducts4Table: [],
      tableColums: [],
    };
  },
  computed: {
    leval() {
      // 动态列的个数（此次组件最多一个【总列数减去开头结尾固定列】）
      return this.levalCount - 2;
    },
    allSelectedProducts() {
      // 所有选中项
      var products = this.getAllSeletedProducts();
      return products;
    },
    // 源产品列表
    metaProductList() {
      var list = [];

      this.data.forEach((dataItem) => {
        dataItem._preKey = "";
        dataItem._fullKey = dataItem.key;

        list = list.concat(this.getMetaDataList(dataItem.products,dataItem))
      });
      return list;
    },
    // 所有的产品列表：整合源数据列表和动态数据列表
    allProductList() {
      return this.metaProductList.concat(this.dynamicProductList);
    },
  },
  methods: {
    getMetaDataList(products,preProduct)
    {
       var list = [];

        products.forEach((product) => {
          this.$set(product, "_preKey", preProduct._fullKey);
          this.$set(product, "_fullKey", preProduct._fullKey + "," + product.key);

          if (list.filter((i) => i._fullKey == product._fullKey).length == 0)
            list.push(product);

          if(product.products&&product.products.length>0)
            list = list.concat(this.getMetaDataList(product.products,product))
        });
        return list;
    },

    // 点击字母事件
    onLetterLiClick(item, index) {
      this.letterIndex = index; // 当前选中字母颜色
      let currOffsetTop = document.getElementsByClassName(
        `first-col-${item}`
      )[0].offsetTop;
      let country = document.getElementsByClassName("panel-body-first")[0];
      country.scrollTop = currOffsetTop;
    },
    // 层级点击事件
    onLevalClick(product, prekey, leval) {
      this.$set(
        this.productLists,
        leval,
        this.allProductList.filter((p) => p._preKey == prekey)
      );
      //将当前载入的层级后面的层级的数据置空，不显示
      Object.keys(this.productLists).forEach((k) => {
        if (Number(k) > leval) {
          this.$set(this.productLists, Number(k), []);
          this.$set(this.selectedItems, Number(k), undefined);
        }
      });
      //设置当前层级的选中项为当前产品
      this.$set(this.selectedItems, Number(leval), product);
    },
    // 数据载入回调
    dataLoaderCallback(product, productChildren) {
      if (productChildren && productChildren instanceof Array) {
        productChildren.forEach((item) => {
          this.$set(item, "_preKey", product._fullKey);
          this.$set(item, "_fullKey", product._fullKey + "," + item.key);
          this.$set(
            item,
            "_column_" + (product._fullKey.split(",").length - 1),
            product.name
          );
          if (
            this.dynamicProductList.filter((i) => i._fullKey == item._fullKey)
              .length == 0
          )
            this.dynamicProductList.push(item);
        });
      }
    },
    getProductChildrenByLeval(leval) {
      if (!this.selectedItems[leval]) return [];
      return this.getProductListByPreKey(this.selectedItems[leval]._fullKey);
    },
    getProductListByPreKey(prekey) {
      return this.allProductList.filter((p) => p._preKey == prekey);
    },
    /**选中选项（最后一列） */
    selectItem(fullkey) {
      this.allProductList
        .filter((p) => p._fullKey == fullkey)
        .forEach((p) => {
          this.$set(p, "_selected", !p._selected);
        });
    },
    selectAllCallback(checked, products, prekey) {
      if (prekey.split(",").length == this.levalCount) {
        products.forEach((p) => this.$set(p, "_selected", checked));
      } else {
        products.forEach((p) => this.selectAll(checked, p._fullKey));
      }
    },
    /*选中所有：当前已选中部分，则清空，否则选中所有 （同时将选中的product记录是为了后面获取选中列表方便）*/
    selectAll(checked, prekey) {
      var products = this.allProductList.filter((p) => p._preKey == prekey);

      //判断是否已经载入了数据，是则不重新载入
      if (products.length == 0) {
        //通过外部 loader 获取数据
        //leval+1 是为了方便调用者清楚对应的层级，但是实际上我们只处理  动态层级，即动态载入数据的 层级

        var product = this.allProductList.filter(
          (p) => p._fullKey == prekey
        )[0];

        this.dataLoader(
          product,
          product.key,
          product._fullKey.split(",").length,
          (productChildren) => {
            this.dataLoaderCallback(product, productChildren);

            this.selectAllCallback(
              checked,
              this.allProductList.filter((p) => p._preKey == prekey),
              prekey
            );
          }
        );
      } else {
        //如果是最后一级的数据，则标记勾选

        this.selectAllCallback(checked, products, prekey);
      }
    },
    isAllSelectedByLeval(leval) {
      if (!this.selectedItems[leval]) return false;
      return this.isAllSelected(this.selectedItems[leval]._fullKey);
    },
    //判断是全选
    isAllSelected(prekey) {
      //判断其子项下()是否都有载入完（有最后一项的数据  ）
      let _this = this;
      var childrenLoadInfo = this.allProductList
        .filter((p) => p._preKey == prekey) //获取到当前列
        .map((p) => {
          //遍历当前列的每一项，判断它们是否有载入子项
          return _this.allProductList.filter(
            (child) =>
              child._fullKey.indexOf(p._fullKey) == 0 && //是否是子项
              child._preKey.split(",").length == _this.levalCount //是否是最后一项
          ).length > 0
            ? 1
            : 0;
        });

      var products = this.allProductList.filter(
        (p) =>
          p._preKey.indexOf(prekey) == 0 &&
          p._fullKey.split(",").length == this.levalCount + 1
      );
      var selectedProducts = products.filter(
        (p) => p._preKey.indexOf(prekey) == 0 && p._selected
      );
      return (
        childrenLoadInfo.length != 0 &&
        childrenLoadInfo.length ==
          childrenLoadInfo.filter((load) => load).length &&
        products.length != 0 &&
        products.length == selectedProducts.length
      );
    },
    /*获取选中的总数  基于当前 product 子集的选中总数*/
    getSelectedCount(prekey) {
      return this.allProductList.filter(
        (p) => p._preKey.indexOf(prekey) == 0 && p._selected
      ).length;
    },
    // 获取所有选中的项
    getAllSeletedProducts() {
      var products = this.allProductList.filter((p) => p._selected);

      return products;
    },
    deleteFromAllSeletedProducts(key) {
      this.allProductList
        .filter((p) => p.key == key)
        .forEach((p) => {
          this.$set(p, "_selected", false);
        });
    },
    // 显示已选
    showSelected() {
      // 所有选中项
      var products = this.getAllSeletedProducts();
      let _this = this;
      products.forEach((product) => {
        var fullkeys = product._fullKey.split(",");
        for (let i = 1; i < fullkeys.length; i++) {
          var p = _this.allProductList.filter((p) => p.key == fullkeys[i])[0];
          _this.$set(product, "_column_" + (i - 1), p.name);
        }
      });
      this.allSelectedProducts4Table = products;
      // 列
      var colums = [];
      if (this.allSelectedProducts && this.allSelectedProducts.length > 0) {
        for (let i = 0; i < this.selectedTableColumnTitles.length - 1; i++) {
          colums.push({
            title: this.selectedTableColumnTitles[i],
            dataIndex: "_column_" + i,
            key: "key_"+i,
          });
        }
        colums.push({
          title: this.selectedTableColumnTitles[
            this.selectedTableColumnTitles.length - 1
          ],
          dataIndex: "name",
          key: "name",
        });
      }
      colums.push({
        title: "Action",
        key: "action",
        scopedSlots: { customRender: "action" },
      });
      this.tableColums = colums;
      this.isShowSelected = true;
      // console.log(this.allSelectedProducts4Table)
    },
    checkAll(checked) {
      //TODO
      if (checked) this.data.forEach((d) => this.selectAll(true, d._fullKey));
      else this.allProductList.forEach((p) => (p._selected = false));
    },
    onConfirm(){
      var statics ={};
      this.allSelectedProducts4Table.forEach(p=>{
        var fullkeys = p._fullKey.split(',');
        for(let i=0;i<fullkeys.length;i++)
        {
          if(!statics[i])statics[i]=[];
          if(!statics[i].includes(fullkeys[i]))statics[i].push(fullkeys[i])
        }       
      })     
      // console.log(statics);
      this.$emit('confirmData',data)
    }
  }
};
</script>
<style scoped lang="less">
ul,
li {
  list-style: none;
  margin: 0px;
  padding: 0px;
}
.layout {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
@panel: panel;
.@{panel} {
  &-body {
    border-bottom: 1.6px solid #ecedf2;
    &-index {
      background: #f6f7fa;
      overflow-y: auto;
      border-right: 1.6px solid #ecedf2;
      ul {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        li {
          font-size: 15.62px;
          color: #9aa3b6;
          text-align: center;
          line-height: 28.12px;
          cursor: pointer;
        }
        .letter-li {
          color: #4f6ef2;
        }
      }
    }
    &-first {
      border-right: 1.6px solid #ecedf2;
      .first-col {
        overflow-y: auto;
        div {
          background: #f6f7fa;
          height: 46.9px;
          line-height: 46.9px;
          padding-left: 17px;
        }
        ul {
          margin-bottom: unset !important;
        }
      }
    }
    &-auto {
      height: 100%;
      border-right: 1.6px solid #ecedf2;
      div {
        height: 100%;
        .ant-checkbox-wrapper {
          padding: 10px 0px 16px 17px;
        }
        .auto-col {
          overflow-y: auto;
        }
      }
    }
    &-last {
      height: 100%;
      div {
        height: 100%;
        .last-all-checkbox {
          padding: 10px 0px 16px 17px;
        }
        .last-col {
          overflow-y: auto;
        }
      }
    }
  }
  &-footer {
    height: 69px;
    .layout();
  }
}
.common-input /deep/ .ant-input {
  font-size: 14px;
}
.active-li {
  background: #ebf0ff;
}
.active-li span {
  color: #4f6ef2;
}
.panel-body-first ul li,
.panel-body-auto ul li,
.panel-body-last ul li {
  height: 46.9px;
  line-height: 46.9px;
  padding-left: 17px;
  cursor: pointer;
  .layout();
}
</style>
